package com.lin.lock.controller;

import com.lin.lock.util.RedisUtil;
import com.sun.org.apache.regexp.internal.RE;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;

import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Create by linjh on
 */
@RestController
public class GoodsController {

    private static final String REDIS_LOCK = "linLock";

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Value("${server.port}")
    private String serverPort;

    private final Lock lock=new ReentrantLock();

    @Autowired
    private Redisson redisson;

    @GetMapping("/buy_goods")
    public String buy_Goods() throws Exception {

        String value= UUID.randomUUID().toString()+Thread.currentThread().getName();

        RLock redissonLock=redisson.getLock(REDIS_LOCK);
        redissonLock.lock();

        try {
            //锁
            Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK, value,10L, TimeUnit.SECONDS);//setnx
            if (!flag){
                return "抢锁失败！！！请重试";
            }
            String result=stringRedisTemplate.opsForValue().get("goods:001");
            int goodsNumber=result==null ? 0 : Integer.parseInt(result);
            if (goodsNumber>0){
                int realNumber=goodsNumber-1;
                stringRedisTemplate.opsForValue().set("goods:001",String.valueOf(realNumber));
                System.out.println("成功买到商品，库存还剩下:"+realNumber+"件"+"\t 服务提供端口"+serverPort);
                return "成功买到商品，库存还剩下:"+realNumber+"件"+"\t 服务提供端口"+serverPort;
            }else {
                System.out.println("商品已经售完/活动结束/服务超时"+"\t 服务提供端口"+serverPort);
            }
            return "商品已经售完/活动结束/服务超时"+"\t 服务提供端口"+serverPort;
        }finally {
            /*//判断加锁和解锁是不是同一客户端
            if (stringRedisTemplate.opsForValue().get(REDIS_LOCK).equalsIgnoreCase(value)){
                //若此时，这把锁不是这个客户端，则会误解锁
                stringRedisTemplate.delete(REDIS_LOCK);
            }

            //Redis事务
            */
            /*while (true){
                stringRedisTemplate.watch(REDIS_LOCK);
                if (stringRedisTemplate.opsForValue().get(REDIS_LOCK).equalsIgnoreCase(value)){
                    stringRedisTemplate.setEnableTransactionSupport(true);
                    stringRedisTemplate.multi();
                    stringRedisTemplate.delete(REDIS_LOCK);
                    List<Object> list = stringRedisTemplate.exec();
                    if (list==null){
                        continue;
                    }
                }
                stringRedisTemplate.unwatch();
                break;
            }
            */

            //Lua脚本
            /*
            Jedis jedis= RedisUtil.getJedis();

            String script="if redis.call('get',KEYS[1]) == ARGV[1] " +
                    "then " +
                    "    return redis.call('del',KEYS[1]) " +
                    "else " +
                    "    return 0 " +
                    "end";
            try {
                Object o = jedis.eval(script, Collections.singletonList(REDIS_LOCK), Collections.singletonList(value));
                if ("1".equals(o.toString())){
                    System.out.println("---del redis lock ok");
                }else {
                    System.out.println("---del redis lock error");
                }
            }finally {
                if (null!=jedis)
                    jedis.close();
            }
             */
            if (redissonLock.isLocked()){
                if (redissonLock.isHeldByCurrentThread()){
                    redissonLock.unlock();
                }
            }
        }

    }
}
